﻿using D.Wx.AppsettingsUtil;
using D.Wx.CacheUtils;
using D.Wx.Dtos;
using D.Wx.Filter;
using D.Wx.IRepository;
using D.Wx.JwtUtil;
using D.Wx.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace D.Wx
{
    /// <summary>
    /// 登录模块
    /// </summary>
    [Route("api/login")]
    public class SysLoginController : BaseApiController
    {
        private readonly ICacheService _cache;
        private readonly ITokenService _tokenService;
        private readonly ISysAdminEntityRepository _sysAdminRepository;
        private readonly IHttpContextAccessor _httpContextAccessor;

        /// <summary>
        /// 构造注入
        /// </summary>
        /// <param name="sysAdminRepository"></param>
        /// <param name="httpContextAccessor"></param>
        /// <param name="tokenService"></param>
        public SysLoginController(ICacheService cache, ISysAdminEntityRepository sysAdminRepository, ITokenService tokenService, IHttpContextAccessor httpContextAccessor)
        {
            _cache = cache;
            _tokenService = tokenService;
            _sysAdminRepository = sysAdminRepository;
            _httpContextAccessor = httpContextAccessor;
        }

        [HttpGet("time")]
        [AllowAnonymous]
        public string Time()
        {
            return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "：" + _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="inputLogin"></param>
        /// <returns></returns>
        [HttpPost("login"), TypeFilter(typeof(ActionFilter))]
        [AllowAnonymous]
        public async Task<ApiResult<string>> Login([FromBody] LoginInput inputLogin)
        {
            var res = new ApiResult<string>()
            {
                Success = false,
                StatusCode = StatusCodeEnum.Waring
            };

            #region 1. 判断用户登录次数限制以及过期时间

            //获得登录次数和过期时间
            var loginConfig = _cache.Get<CacheAdminLogin>(CacheKey.LoginCount + "-" + inputLogin.Account) ?? new CacheAdminLogin();
            if (loginConfig.Account == inputLogin.Account && loginConfig.Count == 4 && loginConfig.DelayMinute != null)
            {
                //说明存在过期时间，需要判断
                if (DateTime.Now <= loginConfig.DelayMinute)
                {
                    res.Msg = "您已连续登录失败超过3次，请稍后3分钟后再试";
                    return res;
                }
                else
                {
                    //已经过了登录的预设时间，重置登录配置参数 
                    loginConfig.Account = inputLogin.Account;
                    loginConfig.Count = 0;
                    loginConfig.DelayMinute = null;
                }
            }
            #endregion

            #region 2.验证用户信息 

            var model = await _sysAdminRepository.Login(inputLogin.Account, inputLogin.Password);
            if (model == null)
            {
                loginConfig.Count++;
                loginConfig.DelayMinute = DateTime.Now.AddMinutes(3);
                _cache.Set(CacheKey.LoginCount + "-" + inputLogin.Account, loginConfig);

                res.Msg = "账户或密码错误";
                return res;
            }
            if (!model.Status.Value)
            {
                res.Msg = "账号已被禁用";
                return res;
            }
            #endregion

            #region 4. 生成token信息，并且返回给前端

            var _appConfig = AppsettingsUtils.Get<AppConfig>();

            var token = _tokenService.IssueToken(new TokenModel()
            {
                Id = model.Id,
                NickName = model.NickName,
                Account = model.Account,
                RoleId = model.RoleId,
                ProjectName = "D.Admin",
                Issuer = _appConfig.JwtConfig.Issuer,
                Audience = _appConfig.JwtConfig.Audience,
                Expires = _appConfig.JwtConfig.Expires,
                SecretKey = _appConfig.JwtConfig.SecurityKey
            });

            //清楚缓存
            _cache.Del(CacheKey.LoginCount);

            #endregion

            #region 5. 修改用户登录信息
            model.LoginTotalCount += 1;
            model.LastLoginIp = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
            model.LastLoginTime = DateTime.Now;
            await _sysAdminRepository.Update(model);
            #endregion

            res.Data = token;
            res.Success = true;
            res.StatusCode = StatusCodeEnum.OK;
            return res;
        }


        /// <summary>
        /// 请求刷新Token（以旧换新）
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet("refreshToken"), TypeFilter(typeof(ActionFilter))]
        public async Task<ApiResult<string>> RefreshToken(string token = "")
        {
            string jwtStr = string.Empty;

            if (string.IsNullOrEmpty(token))
            {
                return new ApiResult<string>()
                {
                    Success = false,
                    Msg = "token无效，请重新登录！",
                };
            }
            var tokenModel = _tokenService.SerializeToken(token);
            if (tokenModel != null && !string.IsNullOrEmpty(tokenModel.Id))
            {
                var user = await _sysAdminRepository.Get(tokenModel.Id);
                if (user != null)
                {
                    var refreshToken = _tokenService.IssueToken(tokenModel);
                    return new ApiResult<string>()
                    {
                        Success = true,
                        Msg = "获取成功",
                        Data = refreshToken
                    };
                }
            }

            return new ApiResult<string>()
            {
                Success = false,
                Msg = "认证失败！",
            };
        }


        /// <summary>
        /// 获取用户信息
        /// </summary> 
        /// <returns></returns>
        [HttpGet("getUserInfo"), TypeFilter(typeof(ActionFilter))]
        public async Task<ApiResult<AdminEntityOutput>> GetUserInfo()
        {
            if (AdminId == null)
            {
                return new ApiResult<AdminEntityOutput>()
                {
                    Success = false,
                    StatusCode = StatusCodeEnum.Waring,
                    Msg = "登录过期，请重新登录"
                };
            }
            return new ApiResult<AdminEntityOutput>() { Data = await _sysAdminRepository.Get(AdminId) };
        }

        /// <summary>
        /// 登出操作
        /// </summary>
        /// <returns></returns>

        [HttpPost("logout"), TypeFilter(typeof(ActionFilter))]
        public ApiResult<string> Logout()
        {
            //await HttpContext.SignOutAsync(JwtBearerDefaults.AuthenticationScheme);

            return new ApiResult<string>();
        }
    }
}